/**
 * ReportGear(2011)
 */
package net.abbp.report.view.grid;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Component;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.geom.Rectangle2D;

import javax.swing.JPopupMenu;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.UIManager;

import net.abbp.report.model.Cell;
import net.abbp.report.model.ReportModel;
import net.abbp.report.utils.ReportUtils;
import net.abbp.report.view.GridView;
import net.abbp.report.view.cell.editor.CellEditorEvent;
import net.abbp.report.view.cell.editor.CellEditorListener;
import net.abbp.report.view.cell.editor.ICellEditor;

import com.reportgear.report.model.auxiliary.ColumnPropList;
import com.reportgear.report.model.auxiliary.ColumnRow;
import com.reportgear.report.model.auxiliary.ColumnType;
import com.reportgear.report.model.auxiliary.RowPropList;
import com.reportgear.report.model.auxiliary.RowType;
import com.reportgear.report.view.grid.selection.GridSelection;
import com.reportgear.report.view.grid.selection.Selection;
import com.reportgear.report.view.grid.util.GraphHelper;
import com.reportgear.report.view.grid.util.GridUtils;
import com.reportgear.report.view.grid.util.KeyEventUtils;

/**
 * 编辑GRID
 * 
 * @version 1.0 2011-3-18
 * @author <a herf="lexloo@gmail.com">lexloo</a>
 * @since Report 1.0
 * 
 */
public class Grid extends BaseGridComponent {
    private static final long serialVersionUID = -1467908043805984936L;
    // 拖动刷新时间
    private static final int DRAG_REFRESH_TIME = 100;
    // 移动刷新时间
    private static final int MOVE_REFRESH_TIME = 100;
    // 是否显示网格线
    private boolean showGridLine = true;
    // 功能弹出菜单
    private JPopupMenu gridActionMenu;
    // 网格线颜色
    private Color gridLineColor = Color.LIGHT_GRAY;
    // 显示分页线
    private boolean showPaginateLine = true;
    // 分页线颜色
    private Color paginationLineColor = Color.RED;
    // 选中背景颜色
    private Color selectedBackground = new Color(150, 150, 255);
    // 选中边框颜色
    private Color selectedBorderLineColor = Color.BLACK;
    // 是否可编辑
    private boolean editable = true;
    // 单元格是否可选择
    private boolean cellSelectable = true;
    // 支持单元格编辑
    private boolean supportCellEditorDef = false;
    // 单元格可以编辑
    private boolean cellDragable = true;

    private long lastMouseMoveTime = 0L;

    int oldEvtX = 0;
    int oldEvtY = 0;
    int oldLocationX = 0;
    int oldLocationY = 0;
    private int dragType = GridUtils.DRAG_NONE;
    private String tooltipText = null;
    private Point tooltipLocation = new Point();
    private int tabMoveDirection = 0;
    private int enterMoveDirection = 0;
    transient Component editorComponent;
    /**
     * 当前正在编辑的单元格对象
     */
    private transient Cell editingCell;
    /**
     * 编辑器
     */
    protected transient ICellEditor cellEditor;
    private long keyPressedLastTime = 0L;
    private boolean isKeyPressedContentChanged = false;

    // 是否正在绘制
    private boolean isPainting = false;
    // 临时绘制对象
    private Rectangle2D tmpRectangle2D = new Rectangle2D.Double(0.0D, 0.0D, 0.0D, 0.0D);

    private CellEditorListener innerCellEditorListener = new CellEditorListener() {

        public void editingStopped(CellEditorEvent evt) {
            EventQueue.invokeLater(new Runnable() {

                @Override
                public void run() {
                    Grid.this.stopCellEditingInner(false);
                }
            });
        }

        public void editingCanceled(CellEditorEvent evt) {
            Grid.this.cancelEditing();
        }
    };

    public Grid(GridView gridView) {
        super(gridView);

        this.enableEvents(KeyEvent.MOUSE_EVENT_MASK
                          + KeyEvent.MOUSE_MOTION_EVENT_MASK
                          + KeyEvent.KEY_EVENT_MASK
                          + KeyEvent.MOUSE_WHEEL_EVENT_MASK);

        new GridAction(this);

        setFocusTraversalKeysEnabled(false);
        setOpaque(false);
        ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
        toolTipManager.registerComponent(this);
        toolTipManager.setInitialDelay(1);
        toolTipManager.setReshowDelay(1);
        toolTipManager.setDismissDelay(180000);
    }

    public boolean isShowGridLine() {
        return this.showGridLine;
    }

    public void setShowGridLine(boolean showGridLine) {
        this.showGridLine = showGridLine;
        this.gridView.refresh();
    }

    public Color getGridLineColor() {
        return this.gridLineColor;
    }

    public void setGridLineColor(Color color) {
        Color oldColor = this.gridLineColor;
        this.gridLineColor = color;

        this.firePropertyChange("gridLineColor", oldColor, this.gridLineColor);
        this.repaint();
    }

    public boolean isShowPaginateLine() {
        return this.showPaginateLine;
    }

    public void setShowPaginateLine(boolean showPaginateLine) {
        this.showPaginateLine = showPaginateLine;
        this.gridView.updateUI();
    }

    public Color getPaginationLineColor() {
        return this.paginationLineColor;
    }

    public void setPaginationLineColor(Color newColor) {
        this.paginationLineColor = newColor;
        this.gridView.updateUI();
    }

    public Color getSelectedBackground() {
        return this.selectedBackground;
    }

    public void setSelectedBackground(Color selectedBackground) {
        this.selectedBackground = selectedBackground;
        this.gridView.updateUI();
    }

    public Color getSelectedBorderLineColor() {
        return this.selectedBorderLineColor;
    }

    public void setSelectedBorderLineColor(Color newColor) {
        this.selectedBorderLineColor = newColor;
        this.gridView.updateUI();
    }

    public boolean isEditable() {
        return this.editable;
    }

    public void setEditable(boolean editable) {
        this.editable = editable;
    }

    public boolean isSupportCellEditorDef() {
        return this.supportCellEditorDef;
    }

    public void setSupportCellEditorDef(boolean supportCellEditorDef) {
        this.supportCellEditorDef = supportCellEditorDef;
    }

    public boolean isCellDragable() {
        return this.cellDragable;
    }

    public void setCellDragable(boolean cellDragable) {
        this.cellDragable = cellDragable;
    }

    /**
     * 是否正在编辑
     * <p>
     * 编辑器组件不为空
     * 
     * @return
     */
    public boolean isEditing() {
        return (this.editorComponent != null);
    }

    /**
     * 是否正在编辑单元格
     * <p>
     * 正在编辑且单元格编辑器不为空
     * 
     * @return
     */
    public boolean isCellEditing() {
        return ((isEditing()) && (this.cellEditor != null));
    }

    public Component getEditorComponent() {
        return this.editorComponent;
    }

    /**
     * 单元格是是否可编辑
     * 
     * @param column 列
     * @param row 行
     * @return 可编辑状态
     */
    public boolean isCellEditable(int column, int row) {
        if (this.reportModel.getRowType(row) == RowType.NORMAL) {
            return false;
        }

        return true;
    }

    public ICellEditor getCellEditor() {
        return this.cellEditor;
    }

    public void setCellEditor(ICellEditor cellEditor) {
        ICellEditor oldEditor = this.cellEditor;
        this.cellEditor = cellEditor;

        firePropertyChange("CellEditor", oldEditor, this.cellEditor);
    }

    /**
     * 获取Grid中显示的报表
     * 
     * @return
     */
    public ReportModel getReport() {
        return this.gridView.getReportModel();
    }

    /**
     * 开始编辑
     */
    public void startEditing() {
        startEditing(null);
    }

    /**
     * 开始编辑单元格
     * 
     * @param keyEvent
     */
    protected void startEditing(KeyEvent keyEvent) {
        if (isCellSelectable()) {
            Selection rect = this.gridView.getGridSelection().getEditSelection();

            startCellEditingAt(rect.getColumn(), rect.getRow(), keyEvent);
        }
    }

    /**
     * 开始单元格编辑
     * 
     * @param column
     * @param row
     * @return
     */
    public void startCellEditingAt(int column, int row) {
        startCellEditingAt(column, row, null);
    }

    /**
     * 开始单元格编辑
     * 
     * @param column
     * @param row
     * @param keyEvent
     * @return
     */
    private void startCellEditingAt(int column, int row, KeyEvent keyEvent) {
        if (isCellEditing()) {
            stopEditing();
        }

        if ((!isEditable()) || ((row < 0) || (column < 0)) || (!isCellEditable(column, row))) {
            return;
        }

        this.editingCell = this.reportModel.getCell(column, row);

        // 如果编辑单元格为空则新建单元格
        if (this.editingCell == Cell.EMPTY_CELL) {
            this.editingCell = new Cell(column, row);
            this.reportModel.addCell(this.editingCell);
        }

        this.cellEditor = this.editingCell.getCellEditor();

        if (this.cellEditor == null) {
            this.editorComponent = null;
            return;
        }

        this.editorComponent = this.cellEditor.getCellEditorComponent(this, this.editingCell);

        if (this.editorComponent == null) {
            removeCellEditor();
            return;
        }

        this.cellEditor.addCellEditorListener(this.innerCellEditorListener);
        setCellEditor(this.cellEditor);

        if (this.editorComponent instanceof Window) {
            SwingUtilities.invokeLater(new Runnable() {

                public void run() {
                    if (Grid.this.editorComponent == null) {
                        return;
                    }
                    Grid.this.editorComponent.setVisible(true);
                }
            });
        } else {
            if ((keyEvent != null) && (this.editorComponent instanceof JTextField)) {
                ((JTextField) this.editorComponent).setText("");
            }

            if (this.editorComponent != null) {
                ajustEditorComponentBounds(this.gridView, column, row);
                add(this.editorComponent);
            }

            validate();
            repaint(10L);
            if (this.editorComponent != null) {
                this.editorComponent.setVisible(true);
                this.editorComponent.requestFocus();
            }
        }
    }

    /**
     * 停止编辑
     */
    public void stopEditing() {
        stopCellEditingInner(true);
    }

    /**
     * 停止单元格编辑
     * 
     * @param requestFocus 请求焦点
     */
    void stopCellEditingInner(boolean requestFocus) {
        if (!isCellEditing()) {
            return;
        }

        ICellEditor editor = this.cellEditor;
        if (editor == null) {
            if (this.editorComponent != null) {
                remove(this.editorComponent);
            }

            return;
        }

        ReportModel report = getReport();
        Object value = null;
        try {
            value = editor.getCellEditorValue();
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        if (value == null) {
            removeCellEditor();
            return;
        }

        if (this.editingCell != null) {
            this.editingCell.setValue(value);
        }

        removeCellEditor();
        if (!requestFocus || hasFocus()) {
            return;
        }
        requestFocus();
    }

    public void cancelEditing() {
        if (!(isEditing())) {
            return;
        }

        removeCellEditor();
        requestFocus();
    }

    /**
     * 移除单元格编辑器,
     * <p>
     * 每次编辑完成，移除编辑器
     */
    public void removeCellEditor() {
        ICellEditor editor = getCellEditor();
        if (editor == null) {
            return;
        }
        if (this.editorComponent != null) {
            if (this.editorComponent instanceof Window) {
                this.editorComponent.setVisible(false);
                ((Window) this.editorComponent).dispose();
            } else {
                remove(this.editorComponent);
                validate();
            }
        }
        editor.removeCellEditorListener(this.innerCellEditorListener);
        setCellEditor(null);

        this.editorComponent = null;
        this.editingCell = null;

        this.gridView.updateUI();
    }

    @Override
    protected void processMouseMotionEvent(MouseEvent evt) {
        super.processMouseMotionEvent(evt);

        if (!isEnabled()) {
            return;
        }

        switch (evt.getID()) {
        case MouseEvent.MOUSE_MOVED:
            doMouseMoved(evt);
            break;

        case MouseEvent.MOUSE_DRAGGED:
            doMouseDragged(evt);
            break;
        }

    }

    /**
     * 鼠标移动
     * 
     * @param mouseEvent
     */
    private void doMouseMoved(final MouseEvent evt) {
        if (isEditing()) {
            return;
        }

        long lastTime = System.currentTimeMillis();
        if (lastTime - this.lastMouseMoveTime <= MOVE_REFRESH_TIME) {
            return;
        }

        this.lastMouseMoveTime = lastTime;
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                // TODO 处理mouseMoveOnGrid
                // mouseMoveOnGrid(evt.getX(), evt.getY());
            }
        });
    }

    /**
     * 处理鼠标拖动
     * 
     * @param evt 鼠标事件
     */
    private void doMouseDragged(MouseEvent evt) {
        if (isEditing()) {
            return;
        }

        if (SwingUtilities.isRightMouseButton(evt)) {
            return;
        }

        long lastTime = System.currentTimeMillis();
        if (lastTime - this.lastMouseMoveTime <= DRAG_REFRESH_TIME) {
            return;
        }

        this.lastMouseMoveTime = lastTime;

        threadMouseDragged(this.gridView, evt.getX(), evt.getY(), evt.isControlDown());
    }

    @Override
    protected void processMouseWheelEvent(MouseWheelEvent evt) {
        switch (evt.getID()) {
        case MouseEvent.MOUSE_WHEEL:
            int pos = evt.getWheelRotation();
            this.gridView.getVerScrollBar().setValue(this.gridView.getVerScrollBar().getValue() + pos * 5);
        }
    }

    @Override
    protected void processComponentKeyEvent(KeyEvent evt) {
        if (!isEnabled() || !isCellSelectable()) {
            return;
        }

        if (evt.isConsumed()) {
            return;
        }

        KeyEvent keyEvt = KeyEventUtils.processKeyEvent(evt);
        if (keyEvt == null) {
            return;
        }

        switch (keyEvt.getID()) {
        case KeyEvent.KEY_FIRST:
            doKeyTyped(keyEvt);
            break;

        case KeyEvent.KEY_PRESSED:
            doKeyPressed(keyEvt);
            break;

        case KeyEvent.KEY_LAST:
            if (!(this.isKeyPressedContentChanged)) {
                return;
            }

            this.isKeyPressedContentChanged = false;
        }

    }

    private void doKeyTyped(KeyEvent evt) {
        if (evt.isControlDown()) {
            return;
        }

        char keyChar = evt.getKeyChar();

        if (!Character.isDefined(keyChar)) {
            return;
        }

        if (!isCellEditing()) {
            startEditing(evt);
        }

        if ((this.cellEditor == null) || (this.editorComponent == null)) {
            return;
        }

        if (evt.isConsumed()) {
            return;
        }

        this.editorComponent.dispatchEvent(evt);
    }

    private void doKeyPressed(KeyEvent evt) {
        long lastTime = System.currentTimeMillis();
        int keyCode = evt.getKeyCode();
        int j = 0;

        if (lastTime - this.keyPressedLastTime <= 32L) {
            return;
        }
        this.keyPressedLastTime = lastTime;

        switch (keyCode) {
        case KeyEvent.VK_ESCAPE:
            if (isCellEditing()) {
                cancelEditing();
            }

            break;
        case KeyEvent.VK_F2:
            if (!(isCellEditing())) {
                startEditing();
            }

        }

        this.gridView.repaint();
    }

    @Override
    protected void processMouseEvent(MouseEvent evt) {
        super.processMouseEvent(evt);

        if (!isEnabled()) {
            return;
        }

        switch (evt.getID()) {
        case MouseEvent.MOUSE_EXITED:
            break;
        case MouseEvent.MOUSE_ENTERED:
            break;
        case MouseEvent.MOUSE_PRESSED:
            doMousePress(evt);
            break;
        case MouseEvent.MOUSE_RELEASED:
            doMouseReleased(evt);
            break;
        }
    }

    /**
     * 鼠标按下处理
     * 
     * @param x
     * @param y
     */
    public void doMousePress(double x, double y) {
        MouseEvent mouseEvent = new MouseEvent(this, 100, 1L, 0, (int) x, (int) y, 1, false, MouseEvent.BUTTON1);
        doMousePress(mouseEvent);
    }

    /**
     * 鼠标按下处理
     * 
     * @param evt 鼠标事件
     */
    private void doMousePress(MouseEvent evt) {
        stopEditing();

        if (!hasFocus() && isRequestFocusEnabled()) {
            requestFocus();
        }

        int xPos = evt.getX();
        int yPos = evt.getY();
        oldEvtX = xPos;
        oldEvtY = yPos;
        dragType = GridUtils.DRAG_NONE;

        doOneClickSelection(gridView, evt);

        if (SwingUtilities.isRightMouseButton(evt)) {
            showPopupMenu(evt);
        } else {
            if (evt.getClickCount() >= 2) {
                startEditing();
            }
        }
        gridView.repaint();
    }

    /**
     * 释放鼠标
     * 
     * @param evt 鼠标事件
     */
    private void doMouseReleased(MouseEvent evt) {
        if (!isEditable()) {
            return;
        }

        boolean bDirectExit = false;
        GridView worksheet = this.gridView;
        GridSelection gridSel = worksheet.getGridSelection();

        if (gridSel == null) {
            return;
        }

        if (this.dragType == GridUtils.DRAG_CELLSELECTION) {// 拖动选择单元
        } else if (this.dragType == GridUtils.DRAG_CELLSELECTION_BOTTOMRIGHT_CORNER) {// 拖动选择框角落
        }

        this.dragType = GridUtils.DRAG_NONE;

        if (!(bDirectExit)) {
            return;
        }

        worksheet.repaint();
    }

    /**
     * 鼠标拖动处理
     * 
     * @param workSheet 工作sheet
     * @param x x位置
     * @param y y位置
     * @param isCtlDown Ctl是否按下
     */
    protected void threadMouseDragged(GridView workSheet, int x, int y, boolean isCtlDown) {
        GridSelection gridSel = workSheet.getGridSelection();
        boolean needUpdate = false;

        if (this.dragType == GridUtils.DRAG_CELLSELECTION_BOTTOMRIGHT_CORNER) {} else if (this.dragType == GridUtils.DRAG_CELLSELECTION) {// 拖动选择区
        } else if (isCellSelectable()) {// 拖动选择单元格
            Selection sel = gridSel.getLastCellSelection();
            doShiftSelectCell(workSheet, x, y, sel);
            needUpdate = true;
        }

        if (needUpdate) {
            this.gridView.refresh();
        }
    }

    /*
     * 转换单元格选择
     */
    private void doShiftSelectCell(GridView worksheet, double x, double y, Selection selRect) {
        ColumnRow cr = ReportUtils.getAdjustEventColumnRow(worksheet, x, y);
        GridSelection gridSel = worksheet.getGridSelection();
        Selection sel = gridSel.getEditSelection();

        int curX = sel.getColumn();
        int curY = sel.getRow();

        Selection rectSel =
                new Selection(Math.min(curX, cr.getColumn()),
                              Math.min(curY, cr.getRow()),
                              Math.max(sel.getColumSpan(), Math.abs(curX - cr.getColumn()) + 1),
                              Math.max(sel.getRowSpan(), Math.abs(curY - cr.getRow()) + 1));

        selRect.setBounds(rectSel.getColumn(), rectSel.getRow(), rectSel.getColumSpan(), rectSel.getRowSpan());
    }

    /**
     * 处理单元格选择
     * 
     * @param gridView 工作薄
     * @param x x位置
     * @param y y位置
     * @param isShiftDown Shift按下
     * @param isCtlDown Ctl按下
     */
    private void doOneClickSelection(GridView gridView, MouseEvent evt) {
        int x = evt.getX();
        int y = evt.getY();
        boolean isShiftDown = evt.isShiftDown();
        boolean isCtlDown = evt.isControlDown();

        GridSelection gridSel = gridView.getGridSelection();
        if (gridSel == null) {
            return;
        }

        if (isCellSelectable()) {
            gridSel.setType(GridSelection.Type.CELL);
            ColumnRow cr = ReportUtils.getColumnRowByXY(gridView, x, y);
            Selection sel = null;

            if (isShiftDown) {
                if (isCtlDown) {
                    sel = gridSel.getLastCellSelection();
                } else {
                    sel = gridSel.getFirstCellSelection();
                }

                doShiftSelectCell(gridView, x, y, sel);
                gridView.fireGridSelectionChanged();
                return;
            } else if (isCtlDown) {
                doControlSelectCell(gridView, x, y);
                gridView.fireGridSelectionChanged();
                return;
            }

            GridUtils.doSelectCell(gridView, cr.getColumn(), cr.getRow());

            return;
        }

        gridSel.setType(GridSelection.Type.CELL);
        gridSel.clearAllCellSelections();
        gridSel.clearAllFloatName();
    }

    @Override
    public String getToolTipText(MouseEvent paramMouseEvent) {
        return this.tooltipText;
    }

    @Override
    public Point getToolTipLocation(MouseEvent paramMouseEvent) {
        if ((this.tooltipText != null) && (this.tooltipText.length() > 0)) {
            return this.tooltipLocation;
        }

        return null;
    }

    // 界面绘制
    @Override
    public void paintComponent(Graphics g) {
        if (isPainting || (this.reportModel == null)) {
            return;
        }

        isPainting = true;

        Graphics2D g2 = (Graphics2D) g;
        GridView gridView = this.gridView;

        // 填充背景
        Dimension dim = getSize();
        this.tmpRectangle2D.setRect(0.0D, 0.0D, dim.getWidth(), dim.getHeight());
        if (isEnabled()) {
            g2.setPaint(Color.WHITE);
        } else {
            g2.setPaint(UIManager.getColor("control"));
        }
        g2.fill(this.tmpRectangle2D);

        g2.setColor(this.gridLineColor);
        g2.draw(this.tmpRectangle2D);

        ColumnPropList cpl = this.reportModel.getColumnPropList();
        RowPropList crl = this.reportModel.getRowPropList();
        this.drawGridLine(g2, dim, cpl, crl);

        // 绘制对象
        // TODO 注意行列,这里可能有点问题
        int hBegin = gridView.getHoriBeginValue();
        int vBegin = gridView.getVertBeginValue();
        for (int i = 0, colCount = gridView.getHoriValueExtend(); i <= colCount; i++) {
            int column = hBegin + i;
            for (int j = 0, rowCount = gridView.getVertValueExtend(); j <= rowCount; j++) {
                int row = vBegin + j;
                gridView.paintCell(g2, column, row);
                // worksheet.paintCellElementFlag(g2, column, row);
            }
        }
        // --绘制选中区域 开始--
        GridSelection gridSel = gridView.getGridSelection();
        Composite oldComposite = g2.getComposite();
        g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5F));
        g2.setPaint(getSelectedBackground());
        for (int i = 0; i < gridSel.getCellSelectionCount(); i++) {
            Selection sel = gridSel.getCellSelection(i);
            Rectangle rect = this.reportModel.getCellRectangle(this.gridView, sel);

            tmpRectangle2D.setRect(rect.x, rect.y, rect.width, rect.height);
            GraphHelper.fill(g2, tmpRectangle2D);
        }
        g2.setComposite(oldComposite);
        Selection sel = gridSel.getEditSelection();
        Rectangle rect = reportModel.getCellRectangle(this.gridView, sel);
        tmpRectangle2D.setRect(rect.x + 2, rect.y + 2, rect.width - 3, rect.height - 3);
        g2.setPaint(Color.WHITE);
        GraphHelper.fill(g2, tmpRectangle2D);

        gridView.paintCell(g2, sel.getColumn(), sel.getRow(), this.selectedBorderLineColor);
        // worksheet.paintCellElementFlag(g2, sel.getColumn(), sel.getRow());

        if (gridSel.getCellSelectionCount() == 1) {
            Selection sel1 = gridSel.getLastCellSelection();
            Rectangle rect1 = this.reportModel.getCellRectangle(this.gridView, sel);
            tmpRectangle2D.setRect(rect1.x, rect1.y, rect1.width, rect1.height);
            g2.setPaint(getSelectedBorderLineColor());
            GraphHelper.draw(g2, tmpRectangle2D, 5);
        } else {
            Selection sel2 = gridSel.getLastCellSelection();
            Rectangle rect2 = this.reportModel.getCellRectangle(this.gridView, sel);
            tmpRectangle2D.setRect(rect2.x, rect2.y, rect2.width, rect2.height);
            g2.setPaint(getSelectedBorderLineColor());
            GraphHelper.draw(g2, tmpRectangle2D, 1);
        }
        // --绘制选中区域 结束--
        isPainting = false;
    }

    // 绘制网格线
    private void drawGridLine(Graphics2D g2, Dimension dim, ColumnPropList cpl, RowPropList crl) {
        if (!this.showGridLine) {
            return;
        }

        // 绘制行线
        g2.setColor(getGridLineColor());

        double perLen = 0.0D;
        double preLen = 0.0D;
        double nextLen = 0.0D;
        int row = gridView.getVertBeginValue();
        int column = gridView.getHoriBeginValue();
        double h;
        double w;
        int rowCount;
        int columnCount;
        if (this.gridView.isShowActualColumnRow()) {
            rowCount = this.gridView.getRowCount();
            columnCount = this.gridView.getColumnCount();
            w = cpl.getRangeValue(column, columnCount);
            h = crl.getRangeValue(row, rowCount);
        } else {
            w = dim.getWidth();
            h = dim.getHeight();

            rowCount = Integer.MAX_VALUE;
            columnCount = Integer.MAX_VALUE;
        }

        while ((nextLen < h) && (row < rowCount)) {
            preLen += perLen;
            perLen = crl.getHeight(row++);
            if (perLen < 0.001D) {
                nextLen = preLen + 1.0D;
            } else {
                nextLen = preLen + perLen;
            }

            GraphHelper.drawLine(g2, 0.0D, nextLen, w, nextLen);
        }

        // 绘制列线
        perLen = 0;
        preLen = 0;
        nextLen = 0;

        while ((nextLen < w) && (column < columnCount)) {
            preLen += perLen;
            perLen = cpl.getWidth(column++);
            if (perLen < 0.001D) {
                nextLen = preLen + 1.0D;
            } else {
                nextLen = preLen + perLen;
            }

            GraphHelper.drawLine(g2, nextLen, 0.0D, nextLen, h);
        }
    }

    // private void paintTableCellElementTip(Graphics2D paramGraphics2D, double
    // paramDouble1, double paramDouble2,
    // String paramString, LineMetrics paramLineMetrics) {
    // GeneralPath localGeneralPath = new GeneralPath(1);
    // localGeneralPath.moveTo(0.0F, 0.0F);
    // paramDouble1 += ToolTipLeftDistance;
    // double d = paramDouble2 / 2.0D;
    // if (d <= ToolTipLeftDistance) {
    // localGeneralPath.lineTo((float) d, (float) d);
    // } else {
    // localGeneralPath.lineTo(ToolTipLeftDistance, ToolTipLeftDistance);
    // localGeneralPath.lineTo(ToolTipLeftDistance, (float) paramDouble2 -
    // ToolTipLeftDistance);
    // }
    //
    // localGeneralPath.lineTo(0.0F, (float) paramDouble2);
    // localGeneralPath.lineTo((float) paramDouble1, (float) paramDouble2);
    // localGeneralPath.lineTo((float) paramDouble1, 0.0F);
    // localGeneralPath.lineTo(0.0F, 0.0F);
    // paramGraphics2D.setPaint(new Color(212, 208, 200));
    // // GraphHelper.fill(paramGraphics2D, localGeneralPath);
    // // paramGraphics2D.setPaint(Color.gray);
    // // GraphHelper.draw(paramGraphics2D, localGeneralPath);
    // // paramGraphics2D.setPaint(Color.black);
    // // GraphHelper.drawString(paramGraphics2D, paramString,
    // // ToolTipLeftDistance + 2, (paramDouble2 -
    // // paramLineMetrics.getHeight()) / 2.0D + paramLineMetrics.getAscent());
    // }

    /**
     * 按下Control键时选择单元格
     * 
     * @param workSheet 工作薄
     * @param x x位置
     * @param y y位置
     */
    private void doControlSelectCell(GridView workSheet, double x, double y) {
        ReportModel report = workSheet.getReportModel();
        GridSelection gridSel = workSheet.getGridSelection();
        gridSel.setType(GridSelection.Type.CELL);
        ColumnRow columnRow = ReportUtils.getAdjustEventColumnRow(workSheet, x, y);
        Cell cell = report.getCell(columnRow.getColumn(), columnRow.getRow());
        gridSel.setEditBounds(cell.getColumn(), cell.getRow(), cell.getColumnSpan(), cell.getRowSpan());
        gridSel.addCellSelection(new Selection(cell.getColumn(), cell.getRow(), cell.getColumnSpan(), cell.getRowSpan()));
        // TODO 控制可见性
    }

    /**
     * 调整编辑控件位置
     * 
     * @param workSheet 工作薄
     * @param column 列
     * @param row 行
     */
    private void ajustEditorComponentBounds(GridView workSheet, int column, int row) {
        if ((this.editorComponent == null) || (this.editorComponent instanceof Window)) {
            return;
        }

        ReportModel report = workSheet.getReportModel();
        // Cell cell = report.getMergedToCell(column, row);
        Cell cell = report.getCell(column, row);

        RowPropList rhl = report.getRowPropList();
        ColumnPropList cwl = report.getColumnPropList();

        int left;
        int top;
        int width;
        int height;
        left = cwl.getRangeValue(workSheet.getHoriBeginValue(), cell.getColumn());
        top = rhl.getRangeValue(workSheet.getVertBeginValue(), cell.getRow());
        width = cwl.getRangeValue(cell.getColumn(), cell.getColumn() + cell.getColumnSpan()) - 1;
        height = rhl.getRangeValue(cell.getRow(), cell.getRow() + cell.getRowSpan()) - 1;

        this.editorComponent.setLocation(left + 1, top + 1);
        if (this.editorComponent instanceof JTextField) {
            Dimension dim = this.editorComponent.getPreferredSize();
            this.editorComponent.setSize((int) Math.max(width, dim.getWidth() + 1), height);
        } else {
            this.editorComponent.setSize(width, height);
        }

    }

    public int getEnterMoveDirection() {
        return this.enterMoveDirection;
    }

    public void setEnterMoveDirection(int paramInt) {
        this.enterMoveDirection = paramInt;
    }

    public int getTabMoveDirection() {
        return this.tabMoveDirection;
    }

    public void setTabMoveDirection(int paramInt) {
        this.tabMoveDirection = paramInt;
    }

    public boolean isCellSelectable() {
        return this.cellSelectable;
    }

    public void setCellSelectable(boolean paramBoolean) {
        boolean bool = this.cellSelectable;
        this.cellSelectable = paramBoolean;
        firePropertyChange("cellSelectable", bool, this.cellSelectable);
        this.gridView.updateUI();
        this.cellSelectable = paramBoolean;
    }

    /**
     * @return 行总数
     */
    public int getColumnCount() {
        return this.gridView.getColumnCount();
    }

    /**
     * @return 列总数
     */
    public int getRowCount() {
        return this.gridView.getRowCount();
    }

    /**
     * 显示弹出菜单
     * 
     * @param evt
     */
    private void showPopupMenu(MouseEvent evt) {
        if (this.gridActionMenu != null) {
            this.gridActionMenu.show(this, evt.getX(), evt.getY());
        }
    }

    /**
     * 设置功能菜单
     * 
     * @param gridActionMenu 功能菜单
     */
    public void setGridActionMenu(JPopupMenu gridActionMenu) {
        this.gridActionMenu = gridActionMenu;
    }

    // public JToolTip createToolTip() {
    // ScrollToolTip localScrollToolTip = new ScrollToolTip();
    // localScrollToolTip.setComponent(this);
    // return localScrollToolTip;
    // }
}
